package Chatting;
import java.awt.Container;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class Server extends JFrame implements Runnable {

	JTextArea ta = new JTextArea();
	JScrollPane jsp;
	Container cp;

	Vector vc = new Vector();
	ServerSocket server;

	public Server() {
		cp = getContentPane();
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		jsp = new JScrollPane(ta);
		cp.add(jsp);
		setSize(500, 600); // 화면 크기 설정
		setVisible(true); // 화면 출력

		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				for (int i = 0; i < vc.size(); i++) {
					Service sv = (Service) vc.elementAt(i);
					try {
						sv.out.write("800\n");
						sv.out.flush();
						try {
							sv.join();
						} catch (InterruptedException e1) {
							e1.printStackTrace();
						}
						sv.s.close();
					} catch (IOException e1) {
						e1.printStackTrace();
					}
				}
				try {
					server.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				System.exit(0);
			}
		});
	}

	/**
	 * 서버창 메인 메서드
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		Server ss = new Server();
		new Thread(ss).start();
	}

	public void run() {
		try {
			server = new ServerSocket(5000);
			ta.append("서버소켓 생성\n");
		} catch (IOException e) {
			ta.append("서버소켓 실패\n");
			e.printStackTrace();
		}
		while (true) {
			try {
				Socket s = server.accept();
				ta.append("클라이언트 접속 성공~\n");
				Service sv = new Service(s);
				sv.start();
			} catch (IOException e) {
				System.out.println("클라이언트 접속 실패~");
				e.printStackTrace();
			}
		}
	}

	// Server 의 내부 클래스 구현하기 – Service
	public class Service extends Thread {
		String name;
		BufferedReader in = null;
		BufferedWriter out = null;
		Socket s;

		public Service(Socket s) {
			this.s = s;
			try {
				in = new BufferedReader(new InputStreamReader(s
						.getInputStream()));
				out = new BufferedWriter(new OutputStreamWriter(s
						.getOutputStream()));
				// System.out.println("서버IO 생성");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		// ★★ sendAll 메서드 추가(전체 클라이언트에게 메시지를 보내기 위해서 만든 메소드입니다)
		public void sendAll(String msg) {
			int s = vc.size();
			// ta.append("벡터 갯수 : "+s+"\n");

			for (int i = 0; i < s; i++) {
				Service sv = (Service) vc.elementAt(i);
				try {
					sv.out.write(msg + "\n");
					sv.out.flush();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		public void autoScroll() {
			int len = ta.getDocument().getLength();
			ta.setCaretPosition(len);
		}

		public void sendWhom(int code, String na, String message) {
			for (int i = 0; i < vc.size(); i++) {
				Service sv = (Service) vc.elementAt(i);
				if (na.equals(sv.name)) {
					try {
						sv.out.write(code + "|" + name + "|" + message + "\n");
						sv.out.flush();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}

		public void run() {
			while (true) {
				String msg = null;
				try {
					msg = in.readLine();
				} catch (Exception e) {
					System.out.println("read error");
					return;
				}
				ta.append("Server Receive : " + msg + "\n");
				autoScroll();
				StringTokenizer st = new StringTokenizer(msg, "|");
				int num = Integer.parseInt(st.nextToken());
				switch (num) {
				case 100:// 로그인
					name = st.nextToken();
					vc.addElement(this);
					String nickall = "";
					for (int i = 0; i < vc.size(); i++) {
						Service sv = (Service) vc.elementAt(i);
						nickall += sv.name + "%";
					}
					sendAll("100|" + name + "|" + nickall);
					break;
				case 200:// 전체메세지
					msg = st.nextToken();
					sendAll("200|" + name + ">>" + msg);
					break;
				case 300:
					String temp = st.nextToken();// 귓속말상대방
					String message = st.nextToken();
					sendWhom(300, temp, message);
					break;
				case 400:
					String nick = st.nextToken();
					String ppMessage = st.nextToken();
					sendWhom(400, nick, ppMessage);
					break;
				case 500:// 닉네임 변경
					String newName = st.nextToken();
					sendAll("500|" + name + "|" + newName);
					name = newName;
					break;
				case 900:// 나가기
					for (int i = 0; i < vc.size(); i++) {
						Service sv = (Service) vc.elementAt(i);
						if (name.equals(sv.name)) {
							vc.removeElementAt(i);
							break;
						}

					}
					sendAll("900|" + name + "\n");
					try {
						this.join();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					break;

				default:
					break;
				}// switch
			}// while
		}// run
	}// inner class

}
